//////////////////////////////////
//
// uart.c
//
//////////////////////////////////

#include "p18f26k22.h"
#include <GenericTypeDefs.h>
#include "uart.h"

#define OP_BUFFER_SIZE 256

static UINT8 midi_output_buffer[OP_BUFFER_SIZE];

static UINT8 * front_op_buff = midi_output_buffer;
static UINT8 * back_op_buff = midi_output_buffer;

/*
#define IP_BUFFER_SIZE 256
static uint8 midi_input_buffer[IP_BUFFER_SIZE];
static uint8 * front_ip_buff = midi_input_buffer;
static uint8 * back_ip_buff = midi_input_buffer;
*/
void init_debug_uart(void)
{

    TX_OUT = 0b0; //TX output
    RX_IN = 0b1; //RX input

    TXxSTAbits.CSRC = 0b1;  //clock generated from master clock and BRG
    TXxSTAbits.SYNC = 0b0;  //Asynchronous mode
    TXxSTAbits.TX9 = 0b0;   //8 bit transmission
    TXxSTAbits.TXEN = 0b1;  //enable uart
    TXxSTAbits.BRGH = 0b1;  //

    BAUDCONxbits.BRG16 = 0b1;    //8 bit Async
    BAUDCONxbits.ABDEN = 0b0;    //auto baud disabled
    BAUDCONxbits.CKTXP = 0b0;

    RCSTAxbits.SPEN = 0b1;   //serial enable
    RCSTAxbits.CREN = 0b0;   //disables recieve
    RCSTAxbits.RX9 = 0b0;    //8 bit data

    SPBRGHx = 0x01;           //n value to set data rate (9k6 off a 4Mhz Fosc (7 of 16Mhz)
    SPBRGx  = 0xFF;           //0x1FF = 31250 :-) 0x1A0 = 38400

    TXIF = 0b0;
    TXIP = 0b0;
    TXIE = 0b0;
}


void init_uart (void)
{
    TX1STAbits.CSRC = 0b1;  //clock generated from master clock and BRG
    TX1STAbits.SYNC = 0b0;  //Asynchronous mode

    BAUDCONbits.BRG16 = 0b0;    //8 bit Async
    BAUDCONbits.ABDEN = 0b0;    //auto baud disabled

    RCSTAbits.SPEN = 0b0;   //serial enable
    RCSTAbits.CREN = 0b1;   //continuous recieve
    RCSTAbits.RX9 = 0b0;    //8 bit data

    SPBRG = 0x01;           //n value to set data rate (31k25 off a 4Mhz Fosc (7 of 16Mhz)
}

//increments an array pointer
//handles array wrap-around
void increment_buff_pointer(UINT8 ** pointer, UINT8 * buff, UINT16 buff_size)
{
    (*pointer)++;
    if ((*pointer) == (buff + buff_size))
    {
        (*pointer) = buff;
    }
}

//tries to put byte in front of OP FIFO
//onto the transmit buffer
void tx_midi_command_byte(void)
{
    //if data in the OP buffer
    TXIE = 0b0;
    if(back_op_buff != front_op_buff)
    {
        //if transmit not busy
        //if(PIR3bits.TX2IF & TXSTA2bits.TRMT) //
        if(TXIF || TRMT) //interrupts when shift register is clear
        {
            TXRG = *front_op_buff;    //should clear PIR3bits.TX2IF
            increment_buff_pointer(&front_op_buff, midi_output_buffer, OP_BUFFER_SIZE);
        }
    }
    TXIE = !TXIF;
}



//adds a byte to the back of the send FIFO
//will call tx_midi_command_byte()
void buffer_midi_command_byte(UINT8 byte)
{
    increment_buff_pointer(&back_op_buff, midi_output_buffer, OP_BUFFER_SIZE);

    //if buffer is overwritting
    if (back_op_buff == front_op_buff)
    {
        increment_buff_pointer(&front_op_buff, midi_output_buffer, OP_BUFFER_SIZE);
    }
    *back_op_buff = byte;
}

